//------------------------------------------------------------------------------
//  TestRenderApp.cpp
//  (C) 2009 xoyojank
//------------------------------------------------------------------------------
#include "StdAfx.h"
#include "TestRenderApp.h"
#include "Graphics/DDSTextureLoader.h"

using namespace Eddy;

//------------------------------------------------------------------------------
bool
TestRenderApp::Open()
{
	if (RenderApplication::Open())
	{
		// vertex layout
		std::vector<VertexElement> vertexElements;
		vertexElements.push_back(VertexElement(VertexElement::Position, 0, VertexElement::Float3));
		vertexElements.push_back(VertexElement(VertexElement::TexCoord, 0, VertexElement::Float2));
		vertexElements.push_back(VertexElement(VertexElement::Normal, 0, VertexElement::Float3));
		VertexLayoutPtr vertexLayout = new VertexLayout(vertexElements);

		// vertex buffer
		VertexBufferPtr vertexBuffer = new VertexBuffer(VertexBuffer::Static);
		float vertices[] = {-1.0f,-1.0f,0.0f,	0.0f,1.0f,	0.0f,0.0f,1.0f,
							 1.0f,-1.0f,0.0f,	1.0f,1.0f,	0.0f,0.0f,1.0f,
							 0.0f, 1.0f,0.0f,	0.5f,0.0f,	0.0f,0.0f,1.0f};
		vertexBuffer->SetSize(sizeof(vertices));
		vertexBuffer->Write(0, sizeof(vertices), vertices);
		vertexBuffer->SetVertexLayout(vertexLayout);
		
		// primitive group
		PrimitiveGroup primitiveGroup;
		primitiveGroup.SetNumVertices(3);
		primitiveGroup.SetTopologyType(PrimitiveGroup::TriangleStrip);
		std::vector<PrimitiveGroup> primitiveGroups;
		primitiveGroups.push_back(primitiveGroup);

		// mesh
		this->mesh = new Mesh();
		this->mesh->SetVertexBuffer(vertexBuffer);
		this->mesh->SetPrimitiveGroup(primitiveGroups);
		this->mesh->ApplyPrimitiveGroup(0);

		// texture
		this->texture = new Texture();
		DDSTextureLoaderPtr loader = new DDSTextureLoader();
		this->texture->SetName(L"texture\\test_argb.dds");
		this->texture->SetLoader(loader);
		this->texture->Load();

		// effect
		this->effect = EffectManager::Instance()->CreateEffect(L"shader\\lighting.vp.bin",
			L"shader\\lighting.fp.bin");
		this->worldViewMatrix = this->effect->GetVariable("mViewModel");
		this->projectMatrix = this->effect->GetVariable("mProject");
		const EffectVariablePtr& varLightDir = this->effect->GetVariable("vLightDir");
		varLightDir->SetVector(vector(0.5f, -1.0f, -0.5f));
		const EffectVariablePtr& varTexture = this->effect->GetVariable("s_texture");
		varTexture->SetTexture(this->texture);

		matrix44 project = matrix44::orthorh(2.0f, 3.0f, 1.0f, 100.0f);
		this->projectMatrix->SetMatrix(project);

		return true;
	}

	return false;
}

//------------------------------------------------------------------------------
void
TestRenderApp::Close()
{
	this->texture = NULL;
	this->mesh = NULL;
	RenderApplication::Close();
}

//------------------------------------------------------------------------------
void
TestRenderApp::OnRenderFrame()
{

	this->renderDevice->Clear();

	this->renderDevice->BeginPass(this->effect);
	this->renderDevice->Draw();
	this->renderDevice->EndPass();

	this->renderDevice->Present();
}

//------------------------------------------------------------------------------
void
TestRenderApp::OnUpdateFrame()
{
	assert(this->worldViewMatrix.isvalid());
	assert(this->projectMatrix.isvalid());

	// transform matrix
	matrix44 transform = matrix44::rotationy((float)this->GetTime() * 0.0001f);
	transform.scale(vector(0.5f, 0.5f, 0.5f));
	transform.translate(vector(0.5f, 0.5f, 0.0f));

	matrix44 view = matrix44::lookatrh(point(0, 0, 1), point(), vector(0, 1, 0));

	transform = matrix44::multiply(transform, view);
	this->worldViewMatrix->SetMatrix(transform);
}